package org.dtrd.modules.doctor.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.base.BaseController;
import org.dtrd.common.api.vo.Result;
import org.dtrd.common.aspect.annotation.AutoLog;
import org.dtrd.common.util.RedisUtil;
import org.dtrd.common.util.oConvertUtils;
import org.dtrd.config.system.Constant.SuggestType;
import org.dtrd.modules.base.service.BaseCommonService;
import org.dtrd.modules.common.entity.bean.KeyValueBean;
import org.dtrd.modules.doctor.entity.bean.*;
import org.dtrd.modules.doctor.entity.po.DtrdEntRdDoctor;
import org.dtrd.modules.doctor.entity.po.DtrdEntRdSigninSuggest;
import org.dtrd.modules.doctor.entity.request.*;
import org.dtrd.modules.doctor.service.IDtrdEntRdDoctorService;
import org.dtrd.modules.doctor.service.IDtrdEntRdDoctorSigninSuggestService;
import org.dtrd.modules.doctor.service.IDtrdEntRdPatientSigninSuggestService;
import org.dtrd.modules.organization.entity.bean.OrganizationListInfo;
import org.dtrd.modules.system.entity.SysUser;
import org.dtrd.modules.system.service.ISysUserService;
import org.dtrd.modules.util.ShiroUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

import static org.dtrd.common.constant.CommonConstant.*;
import static org.dtrd.config.system.SystemState.ResponseState.*;

/**
 * @author 萧
 * @date:2021-10-18 12:16 下午
 **/
@Api(tags = "医生个人信息")
@RestController
@Slf4j
@RequestMapping(path = {"/201/02", "/doctor"})
public class DoctorController extends BaseController {

    @Autowired
    private IDtrdEntRdDoctorService doctorService;
    @Autowired
    private BaseCommonService baseCommonService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IDtrdEntRdDoctorSigninSuggestService doctorSigninSuggestService;
    @Autowired
    private IDtrdEntRdPatientSigninSuggestService signinSuggestService;
    @Resource
    @Lazy
    private RedisUtil redisUtil;

    @ApiOperation(value = "获取医生详请", response = DoctorInfo.class)
    @PostMapping("/2010201")
    @AutoLog(value = "获取医生详请", operateType = OPERATE_TYPE_QUERY)
    public Result<?> getDoctor(@RequestBody DoctorInfoRequest request) {
        Integer doctorId = request.getDoctorId();
        if (isIntParamInvalid(doctorId) && StrUtil.isBlank(request.getMobile())) {
            return error(STATE_PARAMS_MISSING);
        }
        DoctorInfo info = doctorService.getDoctor(request);
        return Result.OK(info);
    }

    @ApiOperation("新增或修改医生信息")
    @PostMapping("/2010202")
    @AutoLog(value = "新增或修改医生信息", operateType = OPERATE_TYPE_SAVE_OR_UPDATE)
    public Result<?> saveOrUpdateDoctor(@RequestBody @Validated DoctorInfo doctorInfo) {
        String doctorMobile = doctorInfo.getDoctorsMobile();
        Integer doctorId = doctorInfo.getDataId();
        // 校验手机号码
        boolean mobileCheck = doctorService.isInValidMobile(doctorId, doctorMobile);
        if (mobileCheck) {
            return error(STATE_PARAMS_ERROR);
        }
        boolean result = doctorService.saveOrUpdateDoctor(doctorInfo);
        if (result) {
            userService.updateOrgCodeByMobile(doctorInfo.getDoctorsMobile(), doctorInfo.getDoctorsHospitalId());
        }
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation("生成医生二维码")
    @GetMapping("/2010221")
    public Result<?> generateQrCode(@ApiParam(value = "医生ID", required = true) @RequestParam Integer doctorId, @ApiParam(value = "二维码类型 1 添加患者 2 添加团队", required = true, example = "1") @RequestParam Integer qrCodeType) {
        String qrCode = doctorService.generateQrCode(doctorId, qrCodeType);
        log.info("DoctorController.generateQrCode.[doctorId = {}, qrCodeType={}, qrocde={}", doctorId, qrCodeType, qrCode);
        return Result.OK(qrCode);
    }

    @ApiOperation("删除医生信息")
    @DeleteMapping("/2010203")
    @AutoLog(value = "删除医生信息", operateType = OPERATE_TYPE_DELETE)
    public Result<?> removeDoctor(@RequestBody DeleteDoctorRequest request) {
        List<Integer> doctorIds = request.getDoctorIds();
        if (CollectionUtil.isEmpty(doctorIds)) {
            return error(STATE_PARAMS_MISSING);
        }
        boolean result = doctorService.deleteDoctorRecordById(doctorIds);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation(value = "添加医生-后台", notes = "后台的添加医生对应着数据库的所有字段")
    @PostMapping("/2010204")
    @AutoLog(value = "添加医生-后台", operateType = OPERATE_TYPE_SAVE_OR_UPDATE)
    public Result<?> saveDoctor(@RequestBody @Validated DoctorInfo doctorTotalInfo) {
        // 参数有效性校验
        String doctorName = doctorTotalInfo.getDoctorsName();
        String doctorMobile = doctorTotalInfo.getDoctorsMobile();
        Integer doctorType = doctorTotalInfo.getDoctorsType();
        Integer doctorId = doctorTotalInfo.getDataId();
        // 校验手机号码
        boolean mobileCheck = doctorService.isInValidMobile(doctorId, doctorMobile);
        if (mobileCheck) {
            error(STATE_PARAMS_ERROR);
        }
        boolean result = doctorService.saveDoctorByBackstage(doctorTotalInfo);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation(value = "获取医生关联性的机构信息", response = OrganizationListInfo.class)
    @GetMapping("/2010205")
    public Result<?> getDoctorRlOrganization(@RequestParam Integer doctorId) {
        if (isIntParamInvalid(doctorId)) {
            return error(STATE_PARAMS_MISSING);
        }
        List<OrganizationListInfo> organizations = doctorService.getDoctorRlOrganization(doctorId);
        String logContent = String.format("获取医生关联性的机构信息，查询医生id：%d", doctorId);
        baseCommonService.addLog(logContent, OPERATE_TYPE_QUERY);
        return CollectionUtil.isEmpty(organizations) ? error(STATE_NO_RECORD) : Result.OK(organizations);
    }

    @ApiOperation(value = "获取医生执业成就", response = DoctorAchievement.class)
    @GetMapping("/2010206")
    public Result<?> getDoctorAchievement(@RequestParam Integer doctorId) {
        if (isIntParamInvalid(doctorId)) {
            return error(STATE_PARAMS_MISSING);
        }
        DoctorAchievement achievement = doctorService.getDoctorAchievement(doctorId);
        return Result.OK(achievement);
    }

    @ApiOperation(value = "查询本团队之外的医生", notes = "传入 teamId 就会排除此团队的医生, 什么都不传会返回所有医生信息", response = DoctorInfo.class)
    @PostMapping("/2010207")
    public Result<?> getExceptTeamDoctor(@RequestBody TeamDoctorRequest request) {
        List<DoctorInfo> doctorInfos = doctorService.getExceptTeamDoctor(request.getDoctorName(), request.getTeamId());
        String logContent = String.format("查询本团队之外的医生, 查询条件: %s", request);
        baseCommonService.addLog(logContent, OPERATE_TYPE_QUERY);
        return Result.OK(doctorInfos);
    }

    @ApiOperation("更新医生手机号")
    @PostMapping("/2010209")
    public Result<?> updatePatientMobile(@RequestBody JSONObject json) {
        String smscode = json.getString("smscode");
        String phone = json.getString("phone");
        Integer doctorId = json.getInteger("doctorId");
        Result<SysUser> result = new Result<>();
        if (oConvertUtils.isEmpty(doctorId) || oConvertUtils.isEmpty(smscode) || oConvertUtils.isEmpty(phone)) {
            return error(STATE_PARAMS_MISSING);
        }
        if (!doctorService.checkDoctorMobile(phone, doctorId)) {
            result.setMessage("待修改的手机号已存在");
            result.setSuccess(false);
            return result;
        }
        Object object = redisUtil.get(phone);
        if (null == object) {
            result.setMessage("短信验证码失效！");
            result.setSuccess(false);
            return result;
        }
        if (!smscode.equals(object)) {
            result.setMessage("短信验证码不匹配！");
            result.setSuccess(false);
            return result;
        }
        DtrdEntRdDoctor doctor = doctorService.getById(doctorId);
        if (doctor == null) {
            return Result.error("用户不存在!");
        }
        String oldMobile = doctor.getDoctorsMobile();
        SysUser user = userService.getUserByPhone(oldMobile);
        if (user == null) {
            return Result.error("用户不存在！");
        }
        // 更新 patient 表
        doctor.setDoctorsMobile(phone);
        doctorService.updateById(doctor);
        // 更新 sysUser 表
        user.setPhone(phone);
        userService.updateById(user);
        return Result.OK("手机号设置成功!");
    }

    @ApiOperation("同步医生手机号字段")
    @PostMapping("/2010210")
    public Result<?> synchOrSaveDoctorInfoByPhone(@RequestBody JSONObject json) {
        String smscode = json.getString("smscode");
        String phone = json.getString("phone");
        Integer doctorId = json.getInteger("doctorId");
        // 空参校验
        if (oConvertUtils.isEmpty(doctorId) || oConvertUtils.isEmpty(smscode) || oConvertUtils.isEmpty(phone)) {
            return error(STATE_PARAMS_MISSING);
        }
        // 校验验证码
//        Object object = redisUtil.get(phone);
//        if (null == object) {
//            return Result.error("短信验证码失效！");
//        }
//        if (!smscode.equals(object)) {
//            return Result.error("短信验证码不匹配！");
//        }
        doctorId = doctorService.synchOrSaveDoctorInfoByPhone(doctorId, phone);
        // 添加系统日志
        String logContent = String.format("同步医生手机号, 医生id: %d, 手机号: %s", doctorId, phone);
        baseCommonService.addLog(logContent, OPERATE_TYPE_UPDATE);
        return Result.OK(doctorId);
    }

    @ApiOperation("更新医生冻结账号状态")
    @PostMapping("/2010211")
    public Result<?> updateDoctorStatus(@RequestBody DoctorStatusRequest request) {
        //判断doctorId是否是有效的
        if (isIntParamInvalid(request.getDataId())) {
            return error(STATE_PARAMS_ERROR);
        }
        //判断status是否有效，它只能传入0/1;
        if (request.getDoctorsStatus() == 0 || request.getDoctorsStatus() == 1) {
            boolean result = doctorService.updateDoctorStatus(request.getDataId(), request.getDoctorsStatus());
            //这个状态是有问题的，你传status别人又不知道你是过还是没过
            String logContent = String.format("更新医生状态, 操作人: %s, 状态(0-解除冻结,1-冻结): %d", ShiroUtil.getLoginUser(), request.getDoctorsStatus());
            baseCommonService.addLog(logContent, OPERATE_TYPE_UPDATE);
            return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
        } else {
            return error(STATE_PARAMS_ERROR);
        }
    }

    @ApiOperation(value = "查询医生列表", response = DoctorInfo.class)
    @PostMapping(path = {"/2010213", "/list"})
    public Result<?> getDoctorList(@RequestBody DoctorPageRequest request) {
        handlePageRequest(request);
        Integer pageNum = request.getPageNum();
        Integer pageSize = request.getPageSize();
        if (pageNum < 1) {
            List<DoctorInfo> doctorList = doctorService.getDoctorList(request.getOrgCode(), request.getDoctorsName(), request.getDoctorsMobile());
            return Result.OK(doctorList);
        } else {
            IPage<DoctorInfo> doctorInfo = doctorService.listDoctorInfo(pageNum, pageSize, request);
            return Result.OK(doctorInfo);
        }
    }

    /**
     * 根据signinType查询建议列表
     * 根据orgCode进行分类
     * (暂不提供)医生ID不等于0时按照医生的ID与建议类型查询
     *
     * @param request 医生的建议类型
     * @return
     */
    @ApiOperation(value = "查询医生端建议列表", response = DoctorSigninSuggestListInfo.class)
    @PostMapping("/2010214")
    @AutoLog(value = "查询医生端建议列表", operateType = OPERATE_TYPE_QUERY)
    public Result<?> getDoctorSigninSuggestList(@RequestBody SigninSuggestListRequest request) {
        Integer signinType = request.getSigninType();
        if (isIntParamInvalid(signinType)) {
            return error(STATE_DATA_ERROR);
        }
        List<DoctorSigninSuggestListInfo> list = doctorSigninSuggestService.getDoctorSigninSuggestList(request);
        String logContent = String.format("查询医生端建议列表, 查询条件: %s", request.toString());
        baseCommonService.addLog(logContent, OPERATE_TYPE_QUERY);
        return Result.OK(list);
    }

    /**
     * 新增医生端建议
     *
     * @param doctorSigninSuggestDetail 建议信息
     * @return
     */
    @ApiOperation("新增医生端建议")
    @PostMapping("/2010215")
    @AutoLog(value = "新增医生端建议", operateType = OPERATE_TYPE_ADD)
    public Result<?> saveDoctorSigninSuggest(@RequestBody DoctorSigninSuggestDetail doctorSigninSuggestDetail) {
        //判断参数有效性————主要就是判断doctorId、suggestContent、signinType三者的有效性
        Integer doctorId = doctorSigninSuggestDetail.getDoctorId();
        String orgCode = doctorSigninSuggestDetail.getOrgCode();
        String suggestContent = doctorSigninSuggestDetail.getSuggestContent();
        Integer signinType = doctorSigninSuggestDetail.getSigninType();
        if (isIntParamInvalid(doctorId)
                || isIntParamInvalid(signinType)
                || StringUtils.isBlank(orgCode)
                || suggestContent == null) {
            return error(STATE_PARAMS_ERROR);
        }
        boolean result = doctorSigninSuggestService.saveDoctorSigninSuggest(doctorSigninSuggestDetail);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    @ApiOperation("修改医生端建议")
    @PostMapping("/2010220")
    @AutoLog(value = "修改医生端建议", operateType = OPERATE_TYPE_UPDATE)
    public Result<?> updateDoctorSigninSuggest(@RequestBody UpdateSigninSuggestRequest request) {
        //检验字段的有效性
        Integer dataId = request.getDataId();
        String signinContent = request.getSigninContent();
        if (isIntParamInvalid(dataId)
                || signinContent == null) {
            return error(STATE_PARAMS_ERROR);
        }
        //修改建议
        boolean result = doctorSigninSuggestService.updateSigninSuggest(dataId, signinContent);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    /**
     * 批量删除建议
     *
     * @param request 批量删除建议dataIds
     * @return
     */
    @ApiOperation("删除医生端建议")
    @PostMapping("/2010216")
    @AutoLog(value = "删除医生端建议", operateType = OPERATE_TYPE_DELETE)
    public Result<?> removeDoctorSigninSuggest(@RequestBody DeleteDoctorSigninSuggestRequest request) {
        List<Integer> dataIds = request.getDataIds();
        if (CollectionUtil.isEmpty(dataIds)) {
            return error(STATE_PARAMS_MISSING);
        }
        boolean result = doctorSigninSuggestService.removeByIds(dataIds);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    /**
     * 查找所有的建议，所以不需要任何参数
     *
     * @param
     * @return
     */
    @ApiOperation(value = "患者端建议模板", response = SigninSuggestDetail.class)
    @PostMapping("/2010217")
    @AutoLog(value = "患者端建议模板", operateType = OPERATE_TYPE_QUERY)
    public Result<?> getSigninSuggest(@RequestBody SigninSuggestListRequest request) {
        Integer signinType = request.getSigninType();
        if (isIntParamInvalid(signinType)) {
            return error(STATE_PARAMS_ERROR);
        }
        List<String> signinSuggest = doctorSigninSuggestService.getListMouldSigninSuggest(signinType);
        return Result.OK(signinSuggest);
    }

    /**
     * 修改模板库中的内容————只修改建议，其它所有东西都是不动的，而且这个方法仅在这张表中执行修改
     *
     * @param request 修改的建议
     * @return
     */
    @ApiOperation("修改患者端建议")
    @PostMapping("/2010218")
    @AutoLog(value = "修改患者端建议", operateType = OPERATE_TYPE_SAVE_OR_UPDATE)
    public Result<?> updateSigninSuggest(@RequestBody UpdateSigninSuggestRequest request) {
        //判断字段的有效性
        Integer dataId = request.getDataId();
        String signinContent = request.getSigninContent();
        if (isIntParamInvalid(dataId)
                || signinContent == null) {
            return error(STATE_DATA_ERROR);
        }
        boolean result = signinSuggestService.updateSigninSuggest(dataId, signinContent);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    /**
     * 保存到模板————保存到医生的那个链表中
     *
     * @param dtrdEntRdSigninSuggest 患者列表中的信息
     * @return
     */
    @ApiOperation("将建议添加至医生列表")
    @PostMapping("/2010219")
    public Result<?> saveSigninSuggest(@RequestBody DtrdEntRdSigninSuggest dtrdEntRdSigninSuggest) {
        //判断参数的有效性
        Integer signinType = dtrdEntRdSigninSuggest.getSigninType();
        String signinContent = dtrdEntRdSigninSuggest.getSuggestContent();
        if (isIntParamInvalid(signinType) || StrUtil.isBlank(signinContent)) {
            return error(STATE_DATA_ERROR);
        }
        boolean result = doctorSigninSuggestService.saveSigninSuggest(dtrdEntRdSigninSuggest);
        //记录系统日志
        String logContent = String.format("将患者端建议保存至医生端, 操作人: %s", ShiroUtil.getLoginUser());
        baseCommonService.addLog(logContent, OPERATE_TYPE_ADD);
        return result ? Result.OK() : error(STATE_OPERATION_FAILURE);
    }

    /**
     * 建议模板类型
     */
    @ApiOperation(value = "建议模板类型")
    @GetMapping("/2010222")
    @AutoLog(value = "", operateType = OPERATE_TYPE_QUERY)
    public Result<List<KeyValueBean>> getSuggestTemplateTypes() {
        List<KeyValueBean> list = new ArrayList<>();
        SuggestType.effectiveValues().stream().map(suggest -> new KeyValueBean(suggest.getType(), suggest.getName())).forEach(list::add);
        return Result.OK(list);
    }
}
